<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="utf-8">
		<title>Hello world</title>
		<style>
			* {
				margin: 0;
				padding: 0;
			}

			.box {
				position: fixed;
				top: 50%;
				left: 50%;
				margin-top: -40vh;
				margin-left: -40vw;
				width: 80vw;
				height: 80vh;
			}

			.edit-wrapper {
				position: absolute;
				top: 0;
				left: 0;
				z-index: -10;
				opacity: 0;
				/*z-index: 10;
    opacity: 1;*/
				width: 100%;
				height: 100%;
				display: flex;
				justify-content: center;
				align-items: center;
				overflow: hidden;
			}

			.edit-wrapper.is-show {
				z-index: 10;
				opacity: 1;
			}

			.edit-content {
				position: absolute;
				z-index: 10;
				opacity: 1;
				left: 50%;
				top: 50%;
				transform: translate(-50%, -50%);
				transform-origin: center;
			}

			.edit-content .close-btn {
				position: absolute;
				z-index: 50;
				top: 40px;
				right: 40px;
				text-align: center;
				width: 32px;
				height: 32px;
				line-height: 30px;
				border: 1px solid #fff;
				border-radius: 50%;
				font-size: 24px;
				cursor: pointer;
				color: #fff;
				box-sizing: content-box;
			}

			.edit-content .xxb {
				position: absolute;
				z-index: 1;
				bottom: 10px;
				left: 0;
				right: 0;
				text-align: center;
				font-size: 30px;
				color: #409EFF;
			}

			.aa {
				width: 100%;
				height: 100%;
				opacity: 0.5;
			}

			.btn-box {
				position: fixed;
				top: 40px;
				left: 40px;
				z-index: 10;
			}
		</style>
	</head>

	<body>
		<div class="btn-box">
			<button onclick="showEditLineClick()">显示线</button>
			<button onclick="showEditRectClick()">显示矩形</button>
			<button onclick="hideEdit()">隐藏</button>
		</div>
		<div class="box">
			<div class="aa"></div>
			<div class="edit-wrapper">
				<div class="edit-content">
					<div class="close-btn" onclick="oEdit.close()">×</div>
					<div style="width:100%; height:100%;" class="imageContainer"></div>
					<div class="xxb"></div>
				</div>
			</div>
		</div>
		<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
		<script src="./static/hammer.js"></script>
		<script src="./static/cornerstone.min.js"></script>
		<script src="./static/cornerstoneMath.min.js"></script>
		<script src="./static/cornerstoneWADOImageLoader.min.js"></script>
		<script src="./static/cornerstoneWebImageLoader.min.js"></script>
		<script src="./static/cornerstoneTools.min.js"></script>
		<script src="./static/dicomParser.min.js"></script>
		<script>
			const baseUrl = "http://127.0.0.1:8000/static/js/";
			const image_uir = '111'

			var config = {
				"胸膜增厚": "rgb(255, 0, 255)",
				"纤维灶": "rgb(220, 20, 60)",
				"钙化": "rgb(148, 0, 211)",
				"骨折": "rgb(123, 104, 238)",
				"肺不张": "rgb(0, 0, 205)",
				"肿块": "rgb(30, 144, 255)",
				"结节": "rgb(184, 134, 11)",
				"肺气肿": "rgb(0, 139, 0)",
				"气胸": "rgb(139, 35, 35)",
				"PICC": "rgb(218, 165, 32)",
				"积液": "rgb(255, 140, 0)",
				"积气": "rgb(0, 0, 0)",
				"实变": "rgb(85, 107, 47)",
				"术后金属": "rgb(95, 158, 160)",
				"膈下游离气体": "rgb(9,113,175)",
				"肠道积气扩张": "rgb(4,248,194)",
				"肠道积液液平": "rgb(148, 0, 211)",
				"泌尿系统结石": "rgb(108,227,33)"
			}



			var infos = {
				'111_ctr': {
					center_x: 1277,
					heart_x_begin_left: 936,
					heart_x_end_right: 2100,
					heart_y_begin_left: 1531,
					heart_y_end_right: 1621,
					lung_x_begin: 170,
					lung_x_end: 2348,
					lung_y: 1565,
					ratio: 0.5344,
				},
				'111_current': [{
					"name": "纤维灶",
					"confidence": 0.681,
					"xmin": 941,
					"ymin": 1033,
					"xmax": 1355,
					"ymax": 1318
				}, {
					"name": "结节",
					"confidence": 0.272,
					"xmin": 1175,
					"ymin": 812,
					"xmax": 1241,
					"ymax": 877
				}, {
					"name": "实变",
					"confidence": 0.079,
					"xmin": 947,
					"ymin": 1030,
					"xmax": 1349,
					"ymax": 1294
				}, {
					"name": "结节",
					"confidence": 0.036,
					"xmin": 977,
					"ymin": 1032,
					"xmax": 1124,
					"ymax": 1182
				}]
			}

			window.onload = function() {
				_initCornerstone();

				aaInitCornerstone();
			}

			function _initCornerstone() {
				cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
				cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
				cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
				cornerstoneTools.external.cornerstone = cornerstone;
				cornerstoneTools.external.Hammer = Hammer;

				// Image Loader
				const config = {
					webWorkerPath: `${baseUrl}assets/image-loader/cornerstoneWADOImageLoaderWebWorker.js`,
					taskConfiguration: {
						decodeTask: {
							codecsPath: `${baseUrl}assets/image-loader/cornerstoneWADOImageLoaderCodecs.js`,
						},
					},
				};
				cornerstoneWADOImageLoader.webWorkerManager.initialize(config);
			}

			// 初始化影像
			function aaInitCornerstone() {
				let element = document.querySelector('.aa');
				cornerstone.enable(element);
				cornerstone.loadAndCacheImage(
					'wadouri:http://localhost:8088/static/data/1.2.840.1.19439.0.1000.20220101101114.1153.10000.3383340/1.2.840.113564.12312312360.2022010110184045329.1003000225002'
					).then(function(image) {

					var viewport = cornerstone.getDefaultViewportForImage(element, image);
					cornerstone.displayImage(element, image, viewport);
				});
				element.addEventListener('cornerstoneimagerendered', onImageRendered);
			}

			function onImageRendered(e) {
				oEdit.init(e);
			}

			// 显示编辑线
			function showEditLineClick() {
				oEdit.show('line', infos[image_uir + '_ctr']);
			}

			// 显示编辑线
			function showEditRectClick() {
				oEdit.show('rect', infos[image_uir + '_current']);
			}

			// 隐藏
			function hideEdit() {
				oEdit.close();
			}


			const oEdit = {
				visible: false,
				isInit: false,

				oWrapper: $('.edit-wrapper'),
				oContent: $('.edit-wrapper .edit-content'),
				oContainer: $('.edit-wrapper .imageContainer'),
				oCanvas: null,
				context: null,
                oXxb: $('.edit-wrapper .xxb'),
				// 图片数据
				image: {
					ratio: 0,
					width: 0,
					height: 0,
					file: null
				},
				// 编辑类型，line线，rect方框
				editType: '',
				// 数据
				oldData: null,
				newData: null,
				startData: null,
				// 路径
				paths: [],
				oPath: null,
				// 显示
				show(type, data) {
					this.editType = type;
					this.oldData = JSON.parse(JSON.stringify(data));
					this.newData = JSON.parse(JSON.stringify(data));

					if (type == 'line') {
						this.drawLine();
					} else if (type == 'rect') {
						this.drawRect();
					}
					this.oWrapper.addClass('is-show');
					this.visible = true;
				},
				// 关闭
				close() {
					this.oWrapper.removeClass('is-show');
					this.visible = false;
				},
				// 初始化
				async init(e) {
					if (this.isInit) {
						return;
					}
					this.isInit = true;
					await this.initImageData(e);
					await waitTimeout(50);

					this.initEvent();
				},
				initEvent() {
					let context = this.context;
					var isDown = false;
					var downx = 0,
						downy = 0;

					this.oContainer.on('mousedown', 'canvas', (e) => {
						var canvas = this.oContainer[0].children[0];
						var rect = canvas.getBoundingClientRect();
						var x = e.clientX - rect.left;
						var y = e.clientY - rect.top;
						this.paths.forEach((item) => {
							if (context.isPointInPath(item.path, x, y)) {
								this.oPath = item;
								isDown = true;
								this.startCtr = JSON.parse(JSON.stringify(this.newData));
								downx = e.pageX;
								downy = e.pageY;
							}
						})
					})

					this.oContainer.on('mousemove', 'canvas', (e) => {
						// 如果当前是按下
						if (isDown) {
							var movex = e.pageX - downx;
							var movey = e.pageY - downy;
							if (this.editType == 'line') {
								this.saveLineData(this.oPath.key, this.oPath.dir, movex / this.image.ratio, movey /
									this.image.ratio);
							} else if (this.editType == 'rect') {
								this.saveRectData(this.oPath, movex / this.image.ratio, movey / this.image.ratio);
							}

						} else { // 非按下，移动改变canvas鼠标形状
							var canvas = this.oContainer[0].children[0];
							var rect = canvas.getBoundingClientRect();
							var x = e.clientX - rect.left;
							var y = e.clientY - rect.top;

							for (let i = 0; i < this.paths.length; i++) {
								let item = this.paths[i];
								if (context.isPointInPath(item.path, x, y)) {
									canvas.style.cursor = item.cursor;
									break;
								} else {
									canvas.style.cursor = '';
								}
							}
						}
					})

					window.addEventListener('mouseup', function() {
						isDown = false;
					})
				},

				// 初始化图片宽高
				initImageData(e) {
					let oCanvas = e.target.querySelector('canvas');
					// 保存图片
					var base64 = oCanvas.toDataURL('image/png');
					var imgFile = new Image();
					imgFile.src = base64;
					imgFile.onload = () => {
						var ratio = e.detail.viewport.scale;
						var image = e.detail.image;
						this.image.file = imgFile;
						// 设置宽高
						this.oContent.width(image.width * ratio);
						this.oContent.height(image.height * ratio);

						// 设置图片
						cornerstone.enable(this.oContainer[0]);

						// 设置比例
						this.image.ratio = ratio;

						// 获取ctx对象
						this.oCanvas = this.oContainer[0].children[0];
						this.context = this.oCanvas.getContext('2d');
						// 画图
						this.drawImage();
					}
				},

				// 保存线数据
				saveLineData(key, dir, movex, movey) {
					// 保存线位置数据
					this.newData[key] = (dir == 'x' ? movex : movey) + this.startCtr[key];
					// 计算心胸比
					this.newData.ratio = (this.newData.heart_x_end_right - this.newData.heart_x_begin_left) / (this.newData
						.lung_x_end - this.newData.lung_x_begin);
					// 画线
					this.drawLine();
				},

				// 保存矩形数据
				saveRectData(path, movex, movey) {
					let index = path.index;
					if (path.dir == 'xy') {
						this.newData[index].xmin = movex + this.startCtr[index].xmin;
						this.newData[index].xmax = movex + this.startCtr[index].xmax;
						this.newData[index].ymin = movey + this.startCtr[index].ymin;
						this.newData[index].ymax = movey + this.startCtr[index].ymax;
					} else {
						this.newData[index][path.key] = (path.dir == 'x' ? movex : movey) + this.startCtr[index][path.key];
					}
					// 画矩形
					this.drawRect();
				},

				// 绘制底图
				drawImage() {
					var imgWidth = this.image.file.width;
					var imgHeight = this.image.file.height;
					var imgX = (this.oCanvas.width - imgWidth) / 2;
					var imgY = (this.oCanvas.height - imgHeight) / 2;
					this.context.drawImage(
						this.image.file,
						0, 0,
						imgWidth, imgHeight,
						imgX, imgY,
						imgWidth, imgHeight
					);
				},

				// 画线
				drawLine(data, clear=true) {
                    data = data || this.newData;
                    if(clear) {
                        // 清空画布
                        this.oCanvas.width = this.oCanvas.width;
                        // 绘制底图
                        this.drawImage();
                    }

					let context = this.context;
					let paths = [];
					let ctr = {
                        ratio: data.ratio,
						center_x: data.center_x * this.image.ratio,
						heart_x_begin_left: data.heart_x_begin_left * this.image.ratio,
						heart_x_end_right: data.heart_x_end_right * this.image.ratio,
						heart_y_begin_left: data.heart_y_begin_left * this.image.ratio,
						heart_y_end_right: data.heart_y_end_right * this.image.ratio,
						lung_x_begin: data.lung_x_begin * this.image.ratio,
						lung_x_end: data.lung_x_end * this.image.ratio,
						lung_y: data.lung_y * this.image.ratio,
					};
					let size0 = 15 * this.image.ratio;
					let size1 = 20 * this.image.ratio;
					let size2 = 8 * this.image.ratio;


					let path = null;

					context.beginPath();
					context.lineWidth = size0;
					context.strokeStyle = "green"
					context.moveTo(ctr.lung_x_begin, ctr.lung_y);
					context.lineTo(ctr.lung_x_end, ctr.lung_y);
					context.closePath();
					context.stroke();

					// 绿色中线
					path = new Path2D();
					path.moveTo(ctr.lung_x_begin + size1, ctr.lung_y - size2);
					path.lineTo(ctr.lung_x_end - size1, ctr.lung_y - size2);
					path.lineTo(ctr.lung_x_end - size1, ctr.lung_y + size2);
					path.lineTo(ctr.lung_x_begin + size1, ctr.lung_y + size2);
					paths.push({
						cursor: 'n-resize',
						dir: 'y',
						path: path,
						key: 'lung_y'
					});
					// 绿色左
					path = new Path2D();
					path.moveTo(ctr.lung_x_begin, ctr.lung_y - size2);
					path.lineTo(ctr.lung_x_begin + size1, ctr.lung_y - size2);
					path.lineTo(ctr.lung_x_begin + size1, ctr.lung_y + size2);
					path.lineTo(ctr.lung_x_begin, ctr.lung_y + size2);
					paths.push({
						cursor: 'e-resize',
						dir: 'x',
						path: path,
						key: 'lung_x_begin'
					});
					// 绿色右
					path = new Path2D();
					path.moveTo(ctr.lung_x_end - size1, ctr.lung_y - size2);
					path.lineTo(ctr.lung_x_end, ctr.lung_y - size2);
					path.lineTo(ctr.lung_x_end, ctr.lung_y + size2);
					path.lineTo(ctr.lung_x_end - size1, ctr.lung_y + size2);
					paths.push({
						cursor: 'e-resize',
						dir: 'x',
						path: path,
						key: 'lung_x_end'
					});

					centerX = (ctr.lung_x_begin + ctr.lung_x_end) / 2
					Y = [ctr.lung_y, ctr.heart_y_begin_left, ctr.heart_y_end_right]
					minY = Math.min(...Y)
					maxY = Math.max(...Y)
					context.strokeStyle = "black"
					context.beginPath();
					context.moveTo(centerX, minY - 50*this.image.ratio);
					context.lineTo(centerX, maxY + 50*this.image.ratio);
					context.closePath();
					context.stroke();

					context.strokeStyle = "red"
					context.beginPath();
					context.moveTo(ctr.heart_x_begin_left, ctr.heart_y_begin_left);
					context.lineTo(centerX, ctr.heart_y_begin_left);
					context.closePath();
					context.stroke();

					// 红色线
					path = new Path2D();
					path.moveTo(ctr.heart_x_begin_left + size1, ctr.heart_y_begin_left - size2);
					path.lineTo(centerX, ctr.heart_y_begin_left - size2);
					path.lineTo(centerX, ctr.heart_y_begin_left + size2);
					path.lineTo(ctr.heart_x_begin_left + size1, ctr.heart_y_begin_left + size2);
					paths.push({
						cursor: 'n-resize',
						dir: 'y',
						path: path,
						key: 'heart_y_begin_left'
					});
					// 红色左
					path = new Path2D();
					path.moveTo(ctr.heart_x_begin_left, ctr.heart_y_begin_left - size2);
					path.lineTo(ctr.heart_x_begin_left + size1, ctr.heart_y_begin_left - size2);
					path.lineTo(ctr.heart_x_begin_left + size1, ctr.heart_y_begin_left + size2);
					path.lineTo(ctr.heart_x_begin_left, ctr.heart_y_begin_left + size2);
					paths.push({
						cursor: 'e-resize',
						dir: 'x',
						path: path,
						key: 'heart_x_begin_left'
					});

					context.beginPath();
					context.moveTo(centerX, ctr.heart_y_end_right);
					context.lineTo(ctr.heart_x_end_right, ctr.heart_y_end_right);
					context.closePath();
					context.stroke();

					// 红色线
					path = new Path2D();
					path.moveTo(centerX, ctr.heart_y_end_right - size2);
					path.lineTo(ctr.heart_x_end_right - size1, ctr.heart_y_end_right - size2);
					path.lineTo(ctr.heart_x_end_right - size1, ctr.heart_y_end_right + size2);
					path.lineTo(centerX, ctr.heart_y_end_right + size2);
					paths.push({
						cursor: 'n-resize',
						dir: 'y',
						path: path,
						key: 'heart_y_end_right'
					});
					// 红色右
					path = new Path2D();
					path.moveTo(ctr.heart_x_end_right - size1, ctr.heart_y_end_right - size2);
					path.lineTo(ctr.heart_x_end_right, ctr.heart_y_end_right - size2);
					path.lineTo(ctr.heart_x_end_right, ctr.heart_y_end_right + size2);
					path.lineTo(ctr.heart_x_end_right - size1, ctr.heart_y_end_right + size2);
					paths.push({
						cursor: 'e-resize',
						dir: 'x',
						path: path,
						key: 'heart_x_end_right'
					});

					this.paths = paths.reverse();

					// 设置心胸比
                    this.oXxb.text('心胸比：'+ctr.ratio.toFixed(2));
				},

				// 画矩形
				drawRect(data, clear=true) {
                    data = data || this.newData;
                    if(clear) {
                        // 清空画布
                        this.oCanvas.width = this.oCanvas.width;
                        // 绘制底图
                        this.drawImage();
                    }

					let list = data.map(item => {
						return {
							name: item.name,
							confidence: item.confidence,
							xmin: item.xmin * this.image.ratio,
							ymin: item.ymin * this.image.ratio,
							xmax: item.xmax * this.image.ratio,
							ymax: item.ymax * this.image.ratio,
						}
					});
					let context = this.context;
					let paths = [];

					let path = null;

					let size1 = 60 * this.image.ratio;
					let size2 = 8 * this.image.ratio;
					let size3 = 4 * this.image.ratio;

					for (let i = 0; i < list.length; i++) {
						let item = list[i];
						let confidence = item.confidence;
						let label = item.name;
						let color = config[label];

						if (confidence !== 1) {
							label = label + " " + confidence;
						}

						let xmin = item.xmin;
						let ymin = item.ymin;
						let xmax = item.xmax;
						let ymax = item.ymax;

						context.fillStyle = color;
						context.strokeStyle = color;
						context.lineWidth = size2;
						context.font = size1 + "px 微软雅黑"
						context.beginPath();
						context.moveTo(xmin, ymin);
						context.lineTo(xmin, ymax);
						context.lineTo(xmax, ymax);
						context.lineTo(xmax, ymin);
						context.lineTo(xmin, ymin);
						context.fillText(label, xmin, ymin - 1)
						context.fillRect(xmin, ymin - size1, context.measureText(label).width, size1);
						context.closePath();
						context.stroke();
						context.fillStyle = "white"
						context.fillText(label, xmin, ymin - 1);

						// 添加path
						// 上
						path = new Path2D();
						path.moveTo(xmin + size2, ymin - size2);
						path.lineTo(xmax - size2, ymin - size2);
						path.lineTo(xmax - size2, ymin + size2);
						path.lineTo(xmin + size2, ymin + size2);
						paths.push({
							cursor: 'n-resize',
							dir: 'y',
							path: path,
							key: 'ymin',
							index: i
						});
						// 右
						path = new Path2D();
						path.moveTo(xmax - size2, ymin + size2);
						path.lineTo(xmax - size2, ymax - size2);
						path.lineTo(xmax + size2, ymax + size2);
						path.lineTo(xmax + size2, ymin - size2);
						paths.push({
							cursor: 'e-resize',
							dir: 'x',
							path: path,
							key: 'xmax',
							index: i
						});
						// 下
						path = new Path2D();
						path.moveTo(xmin + size2, ymax - size2);
						path.lineTo(xmax - size2, ymax - size2);
						path.lineTo(xmax - size2, ymax + size2);
						path.lineTo(xmin + size2, ymax + size2);
						paths.push({
							cursor: 's-resize',
							dir: 'y',
							path: path,
							key: 'ymax',
							index: i
						});
						// 左
						path = new Path2D();
						path.moveTo(xmin - size2, ymin + size2);
						path.lineTo(xmin - size2, ymax - size2);
						path.lineTo(xmin + size2, ymax - size2);
						path.lineTo(xmin + size2, ymin + size2);
						paths.push({
							cursor: 'w-resize',
							dir: 'x',
							path: path,
							key: 'xmin',
							index: i
						});
						// 中心
						path = new Path2D();
						path.moveTo(xmin + size2, ymin + size2);
						path.lineTo(xmin + size2, ymax - size2);
						path.lineTo(xmax - size2, ymax - size2);
						path.lineTo(xmax - size2, ymin + size2);
						path.lineTo(xmin + size2, ymin + size2);
						paths.push({
							cursor: 'move',
							dir: 'xy',
							path: path,
							index: i
						});
					}
					this.paths = paths.reverse();
				}
			}


			const waitTimeout = function(time) {
				return new Promise((resolve, reject) => {
					setTimeout(() => {
						resolve();
					}, time);
				})
			}
		</script>
	</body>

</html>
